<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>充电宝柜机模拟器</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.min.js"></script>
    <script src="./jquery.min.js"></script>
    <style>
        :root {
            --primary-color: #00ff9d;
            --secondary-color: #ff00c8;
            --background-color: #1a1a1a;
            --border-color: #00ff9d;
            --text-color: #fff;
            --neon-glow: 0 0 10px var(--primary-color),
                        0 0 20px var(--primary-color),
                        0 0 30px var(--primary-color);
        }

        body {
            margin: 0;
            padding: 0;
            background: var(--background-color);
            color: var(--text-color);
            font-family: 'Orbitron', sans-serif;
            min-height: 100vh;
            overflow: hidden;
        }

        .container {
            display: flex;
            flex-direction: column;
            align-items: center;
            padding: 20px;
            gap: 20px;
        }

        .cabinet-title {
            font-size: 2em;
            color: var(--primary-color);
            text-shadow: var(--neon-glow);
            margin-bottom: 20px;
            text-transform: uppercase;
        }

        .cabinet {
            background: rgba(0, 0, 0, 0.8);
            border: 2px solid var(--border-color);
            border-radius: 15px;
            padding: 20px;
            box-shadow: var(--neon-glow);
            position: relative;
            backdrop-filter: blur(5px);
        }

        .slots-grid {
            display: grid;
            grid-template-columns: repeat(4, 1fr);
            gap: 15px;
            margin-bottom: 20px;
        }

        .slot {
            width: 120px;
            height: 70px;
            border: 2px solid var(--border-color);
            border-radius: 10px;
            background: transparent;
            color: var(--text-color);
            font-size: 1em;
            cursor: pointer;
            transition: all 0.3s ease;
            position: relative;
            overflow: hidden;
        }

        .slot:hover {
            transform: translateY(-2px);
            box-shadow: var(--neon-glow);
        }

        .slot.empty {
            background: rgba(255, 255, 255, 0.1);
        }

        .slot.occupied {
            background: rgba(0, 255, 157, 0.2);
        }

        .controls {
            display: flex;
            gap: 20px;
            margin: 20px 0;
        }

        .theme-switcher {
            position: fixed;
            top: 20px;
            right: 20px;
        }

        .theme-menu {
            display: none;
            position: absolute;
            top: 100%;
            right: 0;
            background: rgba(0, 0, 0, 0.9);
            border: 2px solid var(--border-color);
            border-radius: 10px;
            padding: 10px;
            z-index: 1000;
        }

        .theme-menu.show {
            display: block;
        }

        .theme-btn {
            width: 40px;
            height: 40px;
            border-radius: 50%;
            border: 2px solid var(--border-color);
            cursor: pointer;
            transition: all 0.3s ease;
            margin-bottom: 10px;
        }

        .theme-btn:last-child {
            margin-bottom: 0;
        }

        .theme-btn:hover {
            transform: scale(1.1);
            box-shadow: var(--neon-glow);
        }

        .log-console {
            width: 80%;
            height: 150px;
            background: rgba(0, 0, 0, 0.8);
            border: 2px solid var(--border-color);
            border-radius: 10px;
            color: var(--text-color);
            padding: 10px;
            font-family: 'Courier New', monospace;
            resize: none;
        }

        .modal {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.8);
            z-index: 1000;
            justify-content: center;
            align-items: center;
        }

        .modal-content {
            max-width: 90%;
            max-height: 90%;
            border: 2px solid var(--border-color);
            border-radius: 10px;
            box-shadow: var(--neon-glow);
            position: relative;
            padding-top: 60px;
        }

        .status-indicator {
            position: absolute;
            top: 5px;
            right: 5px;
            width: 10px;
            height: 10px;
            border-radius: 50%;
            background: var(--primary-color);
            box-shadow: var(--neon-glow);
        }

        @keyframes neonPulse {
            0% { opacity: 1; }
            50% { opacity: 0.5; }
            100% { opacity: 1; }
        }

        .neon-text {
            animation: neonPulse 2s infinite;
        }
        .mouse-trail {
            position: fixed;
            pointer-events: none;
            z-index: 9999;
        }

        .mouse-trail-dot {
            position: fixed;
            width: 5px;
            height: 5px;
            background: linear-gradient(45deg, var(--primary-color), var(--secondary-color));
            border-radius: 50%;
            opacity: 0;
            transform: translate(-50%, -50%);
            animation: trailFade 0.8s ease forwards;
        }

        .click-ripple {
            position: fixed;
            border-radius: 50%;
            pointer-events: none;
            background: radial-gradient(circle, var(--primary-color) 0%, transparent 70%);
            transform: translate(-50%, -50%);
            animation: rippleEffect 0.8s ease-out forwards;
            z-index: 9998;
        }

        @keyframes trailFade {
            0% { transform: translate(-50%, -50%) scale(1); opacity: 0.8; }
            100% { transform: translate(-50%, -50%) scale(0.1); opacity: 0; }
        }

        @keyframes rippleEffect {
            0% { transform: translate(-50%, -50%) scale(0); opacity: 0.8; }
            100% { transform: translate(-50%, -50%) scale(4); opacity: 0; }
        }
    </style>
</head>
<body>
    <div class="modal" id="imageModal" onclick="hideModal()">
        <div class="modal-content">
            <h2 class="scan-title neon-text" style="position: absolute; top: 10px; left: 0; right: 0; text-align: center; margin: 0; font-size: 1.8em; color: var(--primary-color); text-shadow: var(--neon-glow);">请主人扫码充电</h2>
            <img id="modalImage" src="gj001.png" style="width: 100%; height: auto;">
        </div>
    </div>
    <div class="container">
        <h1 class="cabinet-title neon-text">充电宝柜机模拟器</h1>
        <div class="theme-switcher">
            <button class="theme-btn" id="theme-toggle" style="background: linear-gradient(45deg, #00ff9d, #ff00c8)"></button>
            <div class="theme-menu">
                <button class="theme-btn" data-theme="cyberpunk" style="background: linear-gradient(45deg, #00ff9d, #ff00c8)"></button>
                <button class="theme-btn" data-theme="matrix" style="background: linear-gradient(45deg, #00ff00, #003300)"></button>
                <button class="theme-btn" data-theme="synthwave" style="background: linear-gradient(45deg, #ff00ff, #00ffff)"></button>
                <button class="theme-btn" data-theme="neonRed" style="background: linear-gradient(45deg, #ff0066, #ff3300)"></button>
                <button class="theme-btn" data-theme="auroraBlue" style="background: linear-gradient(45deg, #00ffff, #0066ff)"></button>
                <button class="theme-btn" data-theme="cyberGold" style="background: linear-gradient(45deg, #ffd700, #ff8c00)"></button>
            </div>
        </div>
        <div class="cabinet">
            <div class="slots-grid">
                <button class="slot occupied" id="cdb001" value="cdb001">仓位 1</button>
                <button class="slot empty" id="cdb002" value="">仓位 2</button>
                <button class="slot empty" id="cdb003" value="">仓位 3</button>
                <button class="slot empty" id="cdb004" value="">仓位 4</button>
                <button class="slot empty" id="cdb005" value="">仓位 5</button>
                <button class="slot empty" id="cdb006" value="">仓位 6</button>
                <button class="slot empty" id="cdb007" value="">仓位 7</button>
                <button class="slot empty" id="cdb008" value="">仓位 8</button>
            </div>
            <div class="controls">
                <button class="slot" id="007" style="background: rgba(255, 255, 255, 0.1)">上报属性测试</button>
                <img height="80" id="qrCode" onclick="showModal()" src="gj001.png" style="border-radius: 10px; border: 2px solid var(--border-color); cursor: pointer;" width="80">
            </div>
        </div>
        <textarea class="log-console" id="content" readonly></textarea>
    </div>
    <script>
        function showModal() {
            document.getElementById('imageModal').style.display = 'flex';
        }

        function hideModal() {
            document.getElementById('imageModal').style.display = 'none';
        }

        // MQTT配置和连接
        const mqttConfig = {
            hostname: '192.168.171.128',
            port: 8083,
            clientId: 'CabinetSimulationPage001',
            timeout: 5,
            keepAlive: 100,
            cleanSession: false,
            ssl: false,
            userName: 'admin',
            password: 'admin123456',
            topic: '/sys/scan/submit/gj001'
        };

        // 主题配置
        const themes = {
            cyberpunk: {
                '--primary-color': '#00ff9d',
                '--secondary-color': '#ff00c8',
                '--background-color': '#1a1a1a',
                '--border-color': '#00ff9d',
                '--text-color': '#fff'
            },
            matrix: {
                '--primary-color': '#00ff00',
                '--secondary-color': '#003300',
                '--background-color': '#000000',
                '--border-color': '#00ff00',
                '--text-color': '#00ff00'
            },
            synthwave: {
                '--primary-color': '#ff00ff',
                '--secondary-color': '#00ffff',
                '--background-color': '#2b1055',
                '--border-color': '#ff00ff',
                '--text-color': '#fff'
            },
            neonRed: {
                '--primary-color': '#ff0066',
                '--secondary-color': '#ff3300',
                '--background-color': '#1a0f0f',
                '--border-color': '#ff0066',
                '--text-color': '#fff'
            },
            auroraBlue: {
                '--primary-color': '#00ffff',
                '--secondary-color': '#0066ff',
                '--background-color': '#001a33',
                '--border-color': '#00ffff',
                '--text-color': '#fff'
            },
            cyberGold: {
                '--primary-color': '#ffd700',
                '--secondary-color': '#ff8c00',
                '--background-color': '#1a1a00',
                '--border-color': '#ffd700',
                '--text-color': '#fff'
            }
        };

        $(function() {
            // MQTT客户端初始化
            const client = new Paho.MQTT.Client(mqttConfig.hostname, mqttConfig.port, mqttConfig.clientId);
            
            const options = {
                invocationContext: {
                    host: mqttConfig.hostname,
                    port: mqttConfig.port,
                    path: client.path,
                    clientId: mqttConfig.clientId
                },
                timeout: mqttConfig.timeout,
                keepAliveInterval: mqttConfig.keepAlive,
                cleanSession: mqttConfig.cleanSession,
                useSSL: mqttConfig.ssl,
                userName: mqttConfig.userName,
                password: mqttConfig.password,
                onSuccess: onConnect,
                onFailure: handleError
            };

            client.connect(options);
            client.onConnectionLost = handleConnectionLost;
            client.onMessageArrived = handleMessageArrived;

            // 主题切换功能
            $('#theme-toggle').click(function(e) {
                e.stopPropagation();
                $('.theme-menu').toggleClass('show');
            });

            $('.theme-menu .theme-btn').click(function() {
                const theme = $(this).data('theme');
                applyTheme(theme);
                $('#theme-toggle').css('background', $(this).css('background'));
                $('.theme-menu').removeClass('show');
            });

            // 点击其他区域关闭主题菜单
            $(document).click(function(e) {
                if (!$(e.target).closest('.theme-switcher').length) {
                    $('.theme-menu').removeClass('show');
                }
            });

            // 初始化仓位点击事件
            $('.slot').not('#007').each(function() {
                const $slot = $(this);
                const slotId = $slot.attr('id');
                const slotNo = slotId.replace('cdb', '');
                
                $slot.click(function() {
                    if ($slot.val()) {
                        // 归还充电宝
                        const powerBankNo = $slot.val().replace('归还', '');
                        $slot.val(powerBankNo)
                            .removeClass('occupied')
                            .css('background', 'rgba(255, 255, 255, 0.1)');
                        const messageNo = generateRandomStr();
                        const tmsg = JSON.stringify({
                            messageNo: messageNo,
                            cabinetNo: 'gj001',
                            powerBankNo: powerBankNo,
                            slotNo: parseInt(slotNo),
                            electricity: 90
                        });
                        send('/sys/powerBank/connected', tmsg);
                    }
                });
            });

            // 属性上报测试按钮事件
            $('#007').click(function() {
                if($('#cdb001').val() === 'cdb001') {
                    const messageNo = generateRandomStr();
                    const tmsg = JSON.stringify({
                        messageNo: messageNo,
                        cabinetNo: 'gj001',
                        powerBankNo: 'cdb001',
                        slotNo: 1,
                        electricity: 100
                    });
                    send('/sys/property/post', tmsg);
                } else {
                    alert('卡槽1未插入充电宝');
                }
            });

            // MQTT相关函数
            function onConnect() {
                logMessage('连接成功');
                client.subscribe(mqttConfig.topic);
            }

            function handleError(e) {
                logMessage(`连接失败: ${e.errorMessage}`);
            }

            function handleConnectionLost(responseObject) {
                if (responseObject.errorCode !== 0) {
                    logMessage(`连接已断开: ${responseObject.errorMessage}`);
                }
            }

            function handleMessageArrived(message) {
                logMessage(`收到消息Topic：${message.destinationName}`);
                logMessage(`收到消息：${message.payloadString}`);

                send('/sys/powerBank/unlock', message.payloadString);

                const $slot = $('#cdb001');
                $slot.val('归还cdb001')
                     .addClass('occupied')
                     .css('background', 'rgba(0, 255, 157, 0.4)');
            }

            function send(topic, message) {
                const msg = new Paho.MQTT.Message(message);
                msg.destinationName = topic;
                client.send(msg);
                
                logMessage(`发布消息Topic：${topic}`);
                logMessage(`发布消息：${message}`);
            }

            // 辅助函数
            function generateRandomStr() {
                return 'mq' + Math.floor(Math.random() * (99999999 - 10000000 + 1) + 10000000);
            }

            function logMessage(message) {
                const $content = $('#content');
                $content.val($content.val() + message + '\n');
                $content.scrollTop($content[0].scrollHeight);
            }

            function updateSlotStyles() {
                $('input').each(function() {
                    $(this).toggleClass('empty', !$(this).val());
                });
            }

            function applyTheme(themeName) {
                const theme = themes[themeName];
                Object.entries(theme).forEach(([property, value]) => {
                    document.documentElement.style.setProperty(property, value);
                });
            }
        });

        // 鼠标轨迹效果
        let trailContainer = $('<div class="mouse-trail"></div>');
        $('body').append(trailContainer);

        $(document).mousemove(function(e) {
            let dot = $('<div class="mouse-trail-dot"></div>');
            dot.css({
                left: e.pageX + 'px',
                top: e.pageY + 'px'
            });
            trailContainer.append(dot);
            setTimeout(() => dot.remove(), 800);
        });

        // 点击动画效果
        $(document).click(function(e) {
            let ripple = $('<div class="click-ripple"></div>');
            ripple.css({
                left: e.pageX + 'px',
                top: e.pageY + 'px',
                width: '20px',
                height: '20px'
            });
            $('body').append(ripple);
            setTimeout(() => ripple.remove(), 800);
        });
</script>
</body>
</html>
